/*******************************************************************
 *   > File Name: rtc.c
 *   > Author: fly
 *   > Mail: XXXXXXXX@icode.com
 *   > Create Time: Sun 08 Mar 2020 10:27:04 PM PDT
 ******************************************************************/
#include "main.h"
#include "int.h"

#define RTC_BASE        (0xE2800000)
#define rINTP           (*((volatile unsigned long*)(RTC_BASE + 0x30)))
#define rRTCCON         (*((volatile unsigned long*)(RTC_BASE + 0x40)))
#define rTICCNT         (*((volatile unsigned long*)(RTC_BASE + 0x44)))
#define rRTCALM         (*((volatile unsigned long*)(RTC_BASE + 0x50)))
#define rALMSEC         (*((volatile unsigned long*)(RTC_BASE + 0x54)))
#define rALMMIN         (*((volatile unsigned long*)(RTC_BASE + 0x58)))
#define rALMHOUR        (*((volatile unsigned long*)(RTC_BASE + 0x5C)))
#define rALMDAY         (*((volatile unsigned long*)(RTC_BASE + 0x60)))
#define rALMMON         (*((volatile unsigned long*)(RTC_BASE + 0x64)))
#define rALMYEAR        (*((volatile unsigned long*)(RTC_BASE + 0x68)))
#define rBCDSEC         (*((volatile unsigned long*)(RTC_BASE + 0x70)))
#define rBCDMIN         (*((volatile unsigned long*)(RTC_BASE + 0x74)))
#define rBCDHOUR        (*((volatile unsigned long*)(RTC_BASE + 0x78)))
#define rBCDDAY         (*((volatile unsigned long*)(RTC_BASE + 0x7C)))
#define rBCDDAYWEEK     (*((volatile unsigned long*)(RTC_BASE + 0x80)))
#define rBCDMON         (*((volatile unsigned long*)(RTC_BASE + 0x84)))
#define rBCDYEAR        (*((volatile unsigned long*)(RTC_BASE + 0x88)))
#define rCURTICCNT      (*((volatile unsigned long*)(RTC_BASE + 0x90)))
#define rRTCLVD         (*((volatile unsigned long*)(RTC_BASE + 0x94)))

//函数功能：把十进制转成BCD码，譬如56转成0x56
unsigned int num_2_bcd(unsigned int num)
{
    //第一步，将56拆成5和6
    //第二部，将5和6组合成0x56
    return (((num/10)<<4) + (num%10));
}

//函数功能：将bcd码转成十进制，譬如0x56转成56
unsigned int bcd_2_num(unsigned int bcd)
{
    return (((bcd & 0xf0)>>4)*10 + (bcd & (0x0f)));
}

void rtc_set_time(const struct rtc_time *p)
{
    //打开rtc的读写开关
    rRTCCON |= (0x1<<0);

    //写rtc的时间寄存器
    rBCDYEAR    = num_2_bcd(p->year - 2000);
    rBCDMON     = num_2_bcd(p->month);
    rBCDDAY     = num_2_bcd(p->day);
    rBCDHOUR    = num_2_bcd(p->hour);
    rBCDMIN     = num_2_bcd(p->minute);
    rBCDSEC     = num_2_bcd(p->second);
    rBCDDAYWEEK = num_2_bcd(p->dayweek);

    //关闭rtc的读写开关
    rRTCCON &= ~(0x1<<0);
}

void rtc_get_time(struct rtc_time *p)
{
    //打开rtc的读写开关
    rRTCCON |= (0x1<<0);

    //读rtc的时间寄存器
    p->year     = bcd_2_num(rBCDYEAR) + 2000;
    p->month    = bcd_2_num(rBCDMON);
    p->day      = bcd_2_num(rBCDDAY);
    p->hour     = bcd_2_num(rBCDHOUR);
    p->minute   = bcd_2_num(rBCDMIN); 
    p->second   = bcd_2_num(rBCDSEC);
    p->dayweek  = bcd_2_num(rBCDDAYWEEK);

    //关闭rtc的读写开关
    rRTCCON &= ~(0x1<<0);
}

void rtc_set_alarm(void)
{
    rALMSEC = num_2_bcd(24);
    rRTCALM |= 1<<0;//Enable Second alarm
    rRTCALM |= 1<<6;//Enable Alarm global
}

void isr_rtc_alarm(void)
{
    static int i = 0;
    printf("rtc alarm , i = %d...\n\r", i++);

    rINTP |= (0x01<<1);
    intc_clearvectaddr();
}
